{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Evaluation.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true,
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/usef-kh/fer/blob/master/notebooks/Evaluation.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "H-aXxou_Zcup"
      },
      "source": [
        "# Setup"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LiWinGjFXVep"
      },
      "source": [
        "import warnings\n",
        "\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "\n",
        "import cv2\n",
        "from PIL import Image\n",
        "from matplotlib import pyplot as plt \n",
        "import os\n",
        "import sys\n",
        "import warnings\n",
        "\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "from sklearn.metrics import precision_score, f1_score, recall_score, confusion_matrix\n",
        "\n",
        "import torch.nn.functional as F\n",
        "from torch.utils.data import DataLoader\n",
        "from torch.utils.data import Dataset\n",
        "\n",
        "import torchvision\n",
        "import torchvision.transforms as transforms\n",
        "\n",
        "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
        "warnings.filterwarnings(\"ignore\")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "K2kiHdXNX8eH"
      },
      "source": [
        "## Dataset"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rfKCU17vYKAJ"
      },
      "source": [
        "class CustomDataset(Dataset):\n",
        "    def __init__(self, images, labels, transform=None):\n",
        "        self.images = images\n",
        "        self.labels = labels\n",
        "        self.transform = transform\n",
        "\n",
        "    def __len__(self):\n",
        "        return len(self.images)\n",
        "\n",
        "    def __getitem__(self, idx):\n",
        "        if torch.is_tensor(idx):\n",
        "            idx = idx.tolist()\n",
        "\n",
        "        img = np.array(self.images[idx])\n",
        "        img = Image.fromarray(img)\n",
        "\n",
        "        if self.transform:\n",
        "            img = self.transform(img)\n",
        "\n",
        "        label = torch.tensor(self.labels[idx]).type(torch.long)\n",
        "        sample = (img, label)\n",
        "\n",
        "        return sample"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aRmuxs4HYErH"
      },
      "source": [
        "def load_data(path='fer2013.csv'):\n",
        "    fer2013 = pd.read_csv(path)\n",
        "    emotion_mapping = {0: 'Angry', 1: 'Disgust', 2: 'Fear', 3: 'Happy', 4: 'Sad', 5: 'Surprise', 6: 'Neutral'}\n",
        "\n",
        "    return fer2013, emotion_mapping"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "z3TVdzO_YGO_"
      },
      "source": [
        "def prepare_data(data):\n",
        "    \"\"\" Prepare data for modeling\n",
        "        input: data frame with labels und pixel data\n",
        "        output: image and label array \"\"\"\n",
        "\n",
        "    image_array = np.zeros(shape=(len(data), 48, 48))\n",
        "    image_label = np.array(list(map(int, data['emotion'])))\n",
        "\n",
        "    for i, row in enumerate(data.index):\n",
        "        image = np.fromstring(data.loc[row, 'pixels'], dtype=int, sep=' ')\n",
        "        image = np.reshape(image, (48, 48))\n",
        "        image_array[i] = image\n",
        "\n",
        "    return image_array, image_label"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cQx97atGYDA8"
      },
      "source": [
        "def get_dataloaders(path='fer2013.csv', bs=64, augment=True):\n",
        "    \"\"\" Prepare train, val, & test dataloaders\n",
        "        Augment training data using:\n",
        "            - cropping\n",
        "            - shifting (vertical/horizental)\n",
        "            - horizental flipping\n",
        "            - rotation\n",
        "\n",
        "        input: path to fer2013 csv file\n",
        "        output: (Dataloader, Dataloader, Dataloader) \"\"\"\n",
        "\n",
        "    fer2013, emotion_mapping = load_data(path)\n",
        "\n",
        "    xtrain, ytrain = prepare_data(fer2013[fer2013['Usage'] == 'Training'])\n",
        "    xval, yval = prepare_data(fer2013[fer2013['Usage'] == 'PrivateTest'])\n",
        "    xtest, ytest = prepare_data(fer2013[fer2013['Usage'] == 'PublicTest'])\n",
        "    mu, st = 0, 255\n",
        "\n",
        "    test_transform = transforms.Compose([\n",
        "        # transforms.Scale(52),\n",
        "        transforms.TenCrop(40),\n",
        "        transforms.Lambda(lambda crops: torch.stack([transforms.ToTensor()(crop) for crop in crops])),\n",
        "        transforms.Lambda(lambda tensors: torch.stack([transforms.Normalize(mean=(mu,), std=(st,))(t) for t in tensors])),\n",
        "    ])\n",
        "\n",
        "    if augment:\n",
        "        train_transform = transforms.Compose([\n",
        "            transforms.RandomResizedCrop(48, scale=(0.8, 1.2)),\n",
        "            transforms.RandomApply([transforms.RandomAffine(0, translate=(0.2, 0.2))], p=0.5),\n",
        "            transforms.RandomHorizontalFlip(),\n",
        "            transforms.RandomApply([transforms.RandomRotation(10)], p=0.5),\n",
        "\n",
        "            transforms.TenCrop(40),\n",
        "            transforms.Lambda(lambda crops: torch.stack([transforms.ToTensor()(crop) for crop in crops])),\n",
        "            transforms.Lambda(lambda tensors: torch.stack([transforms.Normalize(mean=(mu,), std=(st,))(t) for t in tensors])),\n",
        "            transforms.Lambda(lambda tensors: torch.stack([transforms.RandomErasing(p=0.5)(t) for t in tensors])),\n",
        "        ])\n",
        "    else:\n",
        "        train_transform = test_transform\n",
        "\n",
        "    # X = np.vstack((xtrain, xval))\n",
        "    # Y = np.hstack((ytrain, yval))\n",
        "\n",
        "    train = CustomDataset(xtrain, ytrain, train_transform)\n",
        "    val = CustomDataset(xval, yval, test_transform)\n",
        "    test = CustomDataset(xtest, ytest, test_transform)\n",
        "\n",
        "    trainloader = DataLoader(train, batch_size=bs, shuffle=True, num_workers=2)\n",
        "    valloader = DataLoader(val, batch_size=64, shuffle=True, num_workers=2)\n",
        "    testloader = DataLoader(test, batch_size=64, shuffle=True, num_workers=2)\n",
        "\n",
        "    return trainloader, valloader, testloader\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3X9msdtpYL3L"
      },
      "source": [
        "## Model Architecture"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "HdBfat0gkh08"
      },
      "source": [
        "class Logger:\n",
        "    def __init__(self):\n",
        "        self.loss_train = []\n",
        "        self.loss_val = []\n",
        "\n",
        "        self.acc_train = []\n",
        "        self.acc_val = []\n",
        "\n",
        "    def get_logs(self):\n",
        "        return self.loss_train, self.loss_val, self.acc_train, self.acc_val\n",
        "\n",
        "    def restore_logs(self, logs):\n",
        "        self.loss_train, self.loss_val, self.acc_train, self.acc_val = logs\n",
        "\n",
        "    def show_plt(self):\n",
        "\n",
        "        plt.figure()\n",
        "        plt.plot(self.acc_train, 'g', label='Training Acc')\n",
        "        plt.plot(self.acc_val, 'b', label='Validation Acc')\n",
        "        plt.title('Accuracy')\n",
        "        plt.xlabel('Epoch')\n",
        "        plt.ylabel('Acc')\n",
        "        plt.legend()\n",
        "        plt.grid()\n",
        "        plt.show()\n",
        "\n",
        "        plt.figure()\n",
        "        plt.plot(self.loss_train, 'g', label='Training Loss')\n",
        "        plt.plot(self.loss_val, 'b', label='Validation Loss')\n",
        "        plt.title('Loss')\n",
        "        plt.xlabel('Epoch')\n",
        "        plt.ylabel('Loss')\n",
        "        plt.legend()\n",
        "        plt.grid()\n",
        "        plt.show()\n",
        "\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "I9aoI9iKrtEf"
      },
      "source": [
        "class Vgg(nn.Module):\n",
        "    def __init__(self, drop=0.2):\n",
        "        super().__init__()\n",
        "\n",
        "        self.conv1a = nn.Conv2d(in_channels=1, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv1b = nn.Conv2d(64, out_channels=64, kernel_size=3, padding=1)\n",
        "\n",
        "        self.conv2a = nn.Conv2d(64, 128, 3, padding=1)\n",
        "        self.conv2b = nn.Conv2d(128, 128, 3, padding=1)\n",
        "\n",
        "        self.conv3a = nn.Conv2d(128, 256, 3, padding=1)\n",
        "        self.conv3b = nn.Conv2d(256, 256, 3, padding=1)\n",
        "\n",
        "        self.conv4a = nn.Conv2d(256, 512, 3, padding=1)\n",
        "        self.conv4b = nn.Conv2d(512, 512, 3, padding=1)\n",
        "\n",
        "        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n",
        "\n",
        "        self.bn1a = nn.BatchNorm2d(64)\n",
        "        self.bn1b = nn.BatchNorm2d(64)\n",
        "\n",
        "        self.bn2a = nn.BatchNorm2d(128)\n",
        "        self.bn2b = nn.BatchNorm2d(128)\n",
        "\n",
        "        self.bn3a = nn.BatchNorm2d(256)\n",
        "        self.bn3b = nn.BatchNorm2d(256)\n",
        "\n",
        "        self.bn4a = nn.BatchNorm2d(512)\n",
        "        self.bn4b = nn.BatchNorm2d(512)\n",
        "\n",
        "        self.lin1 = nn.Linear(512 * 2 * 2, 4096)\n",
        "        self.lin2 = nn.Linear(4096, 4096)\n",
        "\n",
        "        self.lin3 = nn.Linear(4096, 7)\n",
        "\n",
        "        self.drop = nn.Dropout(p=drop)\n",
        "\n",
        "    def forward(self, x):\n",
        "        x = F.relu(self.bn1a(self.conv1a(x)))\n",
        "        x = F.relu(self.bn1b(self.conv1b(x)))\n",
        "        x = self.pool(x)\n",
        "\n",
        "        x = F.relu(self.bn2a(self.conv2a(x)))\n",
        "        x = F.relu(self.bn2b(self.conv2b(x)))\n",
        "        x = self.pool(x)\n",
        "\n",
        "        x = F.relu(self.bn3a(self.conv3a(x)))\n",
        "        x = F.relu(self.bn3b(self.conv3b(x)))\n",
        "        x = self.pool(x)\n",
        "\n",
        "        x = F.relu(self.bn4a(self.conv4a(x)))\n",
        "        x = F.relu(self.bn4b(self.conv4b(x)))\n",
        "        x = self.pool(x)\n",
        "        \n",
        "        x = x.view(-1, 512 * 2 * 2)\n",
        "        x = F.relu(self.drop(self.lin1(x)))\n",
        "        x = F.relu(self.drop(self.lin2(x)))\n",
        "        x = self.lin3(x)\n",
        "\n",
        "        return x"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ftIu5uNeryFT",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "9be588ed-c7f5-4962-ac89-ef84ac998b20"
      },
      "source": [
        "# Load Trained Model\n",
        "checkpoint = torch.load('VGGNet')\n",
        "net = Vgg().to(device)\n",
        "net.load_state_dict(checkpoint[\"params\"])\n",
        "net.eval()\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "Vgg(\n",
              "  (conv1a): Conv2d(1, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv1b): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv2a): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv2b): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv3a): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv3b): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv4a): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (conv4b): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "  (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
              "  (bn1a): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn1b): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn2a): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn2b): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn3a): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn3b): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn4a): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (bn4b): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
              "  (lin1): Linear(in_features=2048, out_features=4096, bias=True)\n",
              "  (lin2): Linear(in_features=4096, out_features=4096, bias=True)\n",
              "  (lin3): Linear(in_features=4096, out_features=7, bias=True)\n",
              "  (drop): Dropout(p=0.2, inplace=False)\n",
              ")"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 572
        },
        "id": "r669lmrEpZMW",
        "outputId": "dbaaff49-3281-4aaf-fae6-ff8eee853ee5"
      },
      "source": [
        "logger = Logger()\n",
        "logger.restore_logs(checkpoint['logs'])\n",
        "logger.show_plt()"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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VVWff151yhTVP/2pchk13W66SXXHDtWWLSuHhYSozp6tOniw6vnnO9mmTHGGR0SopqaqTp6sOn788csKDXWmAdXu3VU7dlT9j/9wnqemqrpcldO2a6caHu7WqCjVpCTV8HBn+LBhqq1bO9NedpmTr3y+8vtbblHt1Us1Nta5hYaqXned6q23qqakONN166Z69dWqY8aoTp2qes45zrwilRmioytf78iRqn36OM87dVJt29bJ1KNH5fRt2hRq795O9pq2ZVSU6sSJqqNGnfh6a7olJqq2aOG8nmuvdYalpJw4Tfnj3r2ddcTEqI4dW7mtk5MrHycmqv7sZye+1tDQk2dxXp9qWJjqRRepRkaqJiRULqtnT+d1Vc/2X//lbNvy9cfEONsvLMx5Hhnp3MrnGTNG9de/dt5H5dN06KDapUueDhmi2rdv5bRxccevLymp5twxMc7yqs7ncp24/atOA86279y5ctuGhzu3UaOOn7dlS9X27Stvf/qTXXPXrwW9rremVPhvev8mjflLjBaVFh03vPxNVl1ysjN8zhzV669XffvtynGLFqnef79qQYHq2rXOdOeee1jLylS7dnWeh4c7H8Ty5ZcX2BtvrCw2vXo5H8JFi5yCP3p05Yfy0Ucr17d5s+r331c+P3DA+RBMmOB8iHr2dD7YGzeqejyV011yibOsiRNVly9XnTtX9YorVCdN2q2bN6tmZKheeqnqDTc4xeeSS5xp27atLDorV6pec43qiy+qlpU5/4wSElQHDVLdurVyXQcPqu7adeJ2PHpUdcsWZ9zNN6u+9pqznCNHVDMznWnKylTffVd1717ncUmJqtvtZN6wofK94HarbtrkbIuXX1adP1/1jTecTFWVljrrmz9f9a67VC++2CmQ771Xc8Zjx5z7zz93tlFGhjPsgw+c56WlzrDDh53ptm1z8paUqBYXO//Ai4qc7M89t0KLi1XXr1f95hvVH39UHTHCeR/98EPltDt2OH/HTz5xtlF5hpISZ31lZapLl6rm5TnDH3hAdehQ1RUrVLOzK7N/+KHqnXc6OdxuZxsuX16Z5//9P9Vp05xx5csvKXFylZUd/znbsEH100+d9R86pLpkieqaNc7zefOc7bFzp/Pan3jCWU9+vrNtdu1y3nvFxao5Oar//Kfqv//tjC8udl7runWqy5ZVvtbi4srtWb7zVVjovIa5c515q7PC3wQK+6luTaXw78rZpZEPReqN8248YVx5YS4tdT4cZWXO8AEDtGJPCZw9MFXnQ9OqlVbsXZfvmcHxe/kul1OIn37a+ZDfcYez95eV5XxAyuf7xS8qsxw44OytX3pp5YfjZIqKVPfsqSwU1bndlYWjqrps26+/rv3bTna2sx0ay5m+F9xu52/QGAKpMKlaXl/yReG3Nv7TcN+i+1BVZoyeUes0mzfD6NHwj3847ciHDzvD09Od++XLnQNqzz3nHLScPh3+/W+n/fPyy2HNmgIeeCCa0FC47z6nnbJ3b+cGMGMGTJ4Mid5rvcyaBb/9Lfzud5UZUlKc9tzwcKft91QiI5228tq4XBATc+rl1GTYsNrHJSTUb5n+4nJVHrcwJpDZWT11tHr/amatm8X0c6fTKa4TxcVw662wa9fxB44WLHAOgs6Y4RxA2rsXxoypHJ+X5xzA+81vnINMf/ubc9bMa6/Bk0/CPfds4fzznQNvDzzgHAytKiEBzq1yTDk5GV56yTmoWlVERN2KvjGm+bE9/jp67MvHiI+M597z7wWcMzuef945C+Kzzyqn+/RT537r1sphl17q7M2HhMB//7fzT6GoiIozTMLD4Re/cKbt2/coy5Y1zmsyxjRPtsdfB3nH8pi3eR6XtPpPdm6OA5w9eXD21qsW+ar/BMqlpDinIt5+u9N0s2mTc+pkly6NEN4YY6qxwl8H7256lyJ3Efvemc6ECc6wXbsqx48ff/L5U1KcexHnHG9wzkMOsa1vjPEDKz11MGvdLLokdCEzI4m9e529/V27nPb1hx92fvgCcE0tV16s+mOR8sJfvU3eGGMai88Kv4j0FJE1VW5HReQuEUkUkc9EZKv3vkmf2/Fj7o8s2rmI6/r8gm3bnKOlK1c6v1486yy4557KaadX6cFh9mwYOtR5XL7HD5WFv3t33+Y2xpja+Kzwq+oWVR2oqgOBNKAQeA+4F1ioqt2Bhd7nTda9C+8lzBXGT5JuoqTEGbZihbPHn5rqHJh94w2nG4GhQ52DtHPnwvXXO901vP227fEbY5qWxjqr50Jgu6ruEpGJwGjv8JnAYuC3jZTjtKw/uJ5/ff8v7ht5H0WZTqc4YWGVhf/ii53prr3WuYFzWma5xESnb5Kqhg93+g+54IJGeAHGGFMDcX7c5eOViLwMrFbV/xORHFWN9w4X4Ej582rzTAWmAqSkpKTNmTOnXuvOz88npp6/Pnp558u8vvt13jrvLRZ90I+nnurOsGFZfPddPCUlLqZP/4HLLqtDN5mNlLexBVJWCKy8gZQVLK8vnUnWMWPGrFLVISeMqOnnvA15A8KBw0CK93lOtfFHTrUMf3TZUFZWpt3/0V1H/vPnevXVqmlpTgdPjz5a2Z3Ct9/WO1atmstPyf0hkPIGUlZVy+tLgdplw3icvf1M7/NMEWmrqvtFpC1Qh57MG8+sWU63tuff8i5b1yUwLOk3zH7TGfc//+N0RQtO17D9+vkvpzHG1FdjFP7JwPC6E/QAABvjSURBVBtVnn8ATAH+6r1/vxEy1Nnrr8PChcr81v+AF79hdpVx5X3dA5x9ttPHjTHGBBqfnscvItHAT4F3qwz+K/BTEdkK/MT7vMnYtg3cbuGHz8+vGBYT43wLOPts59TMs86yg7PGmMDl0z1+VS0AkqoNy8I5y6fJKS11zs8HYMV/Vgzv1s25shM4v75dsaL+vVUaY4y/WSdtVRzX02ZeZT/FZ511/HStWjVeJmOMaWjWZUMVFZ2txTkd8cR7TzKtXviNMSaQWeHHuWjzsWOwdavzm4Y+997CgQPK+97Dzqmp/stmjDENrdk39ezc6Vwx66mn4O2PciC2kNvHXkFKihAT4/w696KL/J3SGGMazikLv/fMnCJVLfM+DwEiVbXQ1+Eaw5Ytzv2nn8LyRS1xnTuT6/vfCEB0tHNZRGOMCSZ1aepZCLSo8rwF8Llv4jS+bduc+/ffhzKPiwsm/EhcZJx/QxljjA/VpfBHqmp++RPv4xYnmT5grFhR7YpZrTbwq/GD/ZbHGGMaQ13a+AtEZLCqrgYQkTSgyLexfO/YMedi5zk5lcMiB7/LZb3u9F8oY4xpBHUp/HcBb4nIPkCANkAt15oKHJ99Vln0W7Up4VCb17nn9nhaRrT0bzBjjPGxUxZ+VV0hIr0A7yVE2KKqpb6N5VseDzz9NLRsCUePQut+68gZeSv3/PSQv6MZY4zPnbKNX0RuB6JVdb2qrgdiROQ/TzVfU/bnPztXx/rjH2HzZiXvJ79kXNdxdlDXGNMs1OXg7i2qWtESrqpHgFt8F8n3Pv4Yzj8ffv1ryI9dze6iTUzqM8nfsYwxplHUpfC7vFfKAkBEXDgXVwlIx47BmjVw3nnO87c3vk1oSCiX9bzMv8GMMaaR1OXg7gJgrog8531+K/Cx7yL51po1UFICw4Y5Vx97e9PbjO08lsSoRH9HM8aYRlGXPf7fAouA27y374EoX4bylW3b4Gc/cx4PGwYr9q1gW/Y2ru5ztX+DGWNMIzpl4fd21fANkAEMBcYCm3wbyzeWLXNO4Zw+HTp0gNnrZhPhiuDnfX7u72jGGNNoam3qEZEeOJdNnIxzsfS5AKo6pnGiNbzy8/bvvx88ZR7e3PAml/a8lPjIeP8GM8aYRnSyNv7NwDJggqpuAxCR6Y2Sykdyc537li3hm73fkFmQyZW9rvRvKGOMaWQna+q5EtgPpIvICyJyIc4vdwNWbi7ExoLLBe9vfp+wkDAu7n6xv2MZY0yjqrXwq+o8Vb0W6AWk43Td0FpEnhGRcY0VsCHl5ECc9zdaC7YvYORZI+1HW8aYZqcuB3cLVPVfqnop0AH4DudMn4CTm+tcTjG7KJvvM79nTGrAHq4wxph6O61LL6rqEVV9XlUv9FUgX8rNdfb4l+1ahqKMOmuUvyMZY0yja1bX3C1v6lmyawkRrgiGth/q70jGGNPomlXhL2/qmb91PqNSRxERGuHvSMYY0+h8WvhFJF5E3haRzSKySUTOE5FEEflMRLZ67xN8maGqnBwgIoctWVuY0H1CY63WGGOaFF/v8T8JLFDVXsAAnF/83gssVNXuONfzvdfHGQBQdfb4M91bAbikxyWNsVpjjGlyfFb4RSQOuAB4CUBVS7zdO08EZnonmwlc7qsMVRUVgdsNBz1b6RTXiS4JXRpjtcYY0+SIqvpmwSIDgeeBjTh7+6uAO4G9qhrvnUaAI+XPq80/FZgKkJKSkjZnzpx65cjPzyc6OoZHHunJggVtib38N6T9dAUP9HmgXsvztfz8fGJiYvwdo04CKSsEVt5AygqW15fOJOuYMWNWqeqQE0aoqk9uwBDADQzzPn8S+DOQU226I6daVlpamtZXenq67tql6jT2qHLlZP3bl3+r9/J8LT093d8R6iyQsqoGVt5AyqpqeX3pTLICK7WGmurLNv49wB5V/cb7/G1gMJApIm0BvPcHfZgBcK6rWyEqm2Hth/l6lcYY02T5rPCr6gHgRxEpv0j7hTjNPh8AU7zDpgDv+ypDufLCP/bGJdD1Uwa0GeDrVRpjTJNVlytwnYn/Bl4XkXBgB3Ajzj+bN0XkJmAX4POroJQXfun6OZ1jUokJD4y2PWOM8QWfFn5VXYPT1l9do3b5UN4dc0bROs7ucnZjrtoYY5qcZvHL3fI9/ozidZzd2gq/MaZ5a1aF3xOWZYXfGNPsNavCT3i+FX5jTLPXbAp/eItiXK4Qeib1PPUMxhgTxHx9Vk+TcPQohETm0zWph/XIaYxp9prNHr8nLMeaeYwxhmZS+LNzPJSGHrbCb4wxNJPCf/hICUTm0jWhq7+jGGOM3zWLwp+TWwYRR2nfsr2/oxhjjN81i8KfdxSIOEq72Hb+jmKMMX7XLAp/QV4YhOfRNqatv6MYY4zfBX3hLyhwUVIUTnh8NrERsf6OY4wxfhf0hT8zMxKApLZ5fk5ijDFNQ9AX/gMHnMLfrtMxPycxxpimIegL//79TuFPTfVvDmOMaSqCvvAfOBAJYYWc1a6Fv6MYY0yTEPSFf/+BcIjLIDEqwd9RjDGmSWgGhT8C4jOIi4zzdxRjjGkSgr7w5+aGQfRBWka09HcUY4xpEoK+8BcUhEJkLnERtsdvjDEQ5IW/rAyOFYVDZI419RhjjFdQF/6jR0FVIML2+I0xplxQF/7cXO+DyFxr4zfGGK9mUvitqccYY8r59Jq7IpIB5AEewK2qQ0QkEZgLpAIZwNWqesQX668o/BG2x2+MMeUaY49/jKoOVNUh3uf3AgtVtTuw0PvcJ3JynPvw6GLCXeG+Wo0xxgQUfzT1TARmeh/PBC731YrK9/hjW3p8tQpjjAk4oqq+W7jITuAIoMBzqvq8iOSoarx3vABHyp9Xm3cqMBUgJSUlbc6cOae9/vfea8c//tGDdvcP4vWxfz+Tl9Jo8vPziYmJ8XeMOgmkrBBYeQMpK1heXzqTrGPGjFlVpbWlkqr67Aa09963BtYCFwA51aY5cqrlpKWlaX089JAqqKY9Nbxe8/tDenq6vyPUWSBlVQ2svIGUVdXy+tKZZAVWag011adNPaq613t/EHgPGApkikhbAO/9QV+tPzcXJLSY+JgoX63CGGMCjs8Kv4hEi0hs+WNgHLAe+ACY4p1sCvC+rzLk5oJE5tkZPcYYU4UvT+dMAd5zmvEJBf6lqgtEZAXwpojcBOwCrvZVgJwcCInKJTI00lerMMaYgOOzwq+qO4ABNQzPAi701Xqrys0FIo4S5gprjNUZY0xACOpf7s6eDbHX3UhYiBV+Y4wpF9SFPzkZNG63FX5jjKkiqAs/gFvd1tRjjDFVBH/hL3PbHr8xxlQR9IXfox7b4zfGmCqCvvC71U1oiE87ITXGmIAS1IXfU+ZBUWvqMcaYKoK68JeWlQJYU48xxlQR1IXfXeYGsD1+Y4ypIqgLf6nH9viNMaa64C785U09tsdvjDEVgrvw2x6/McacILgLv+3xG2PMCYK78NsevzHGnCC4C7/t8RtjzAmC+iettsdvzJkpLS1lz549FBcXn3S6uLg4Nm3a1Eipzlwg5a1L1sjISDp06EBYWN1qXXAXftvjN+aM7Nmzh9jYWFJTU/FeTa9GeXl5xMbGNmKyMxNIeU+VVVXJyspiz549dO7cuU7LDO6mHtvjN+aMFBcXk5SUdNKib/xLREhKSjrlt7Kqgrvw2x6/MWfMin7Td7p/o+Au/LbHb4wxJwjuwm97/MYEtKysLAYOHMjAgQNp06YN7du3r3heUlJy0nlXrlzJHXfcccp1DB8+vKHiAnDXXXfRvn17ysrKGnS5DSm4D+569/itP35jAlNSUhJr1qwBYMaMGcTExHDPPfdUjHe73YSG1vz5HjJkCEOGDDnlOr788suGCQuUlZXx3nvv0bFjR5YsWcKYMWMabNkNKagronXLbEzDuWvBXaw5sKbGcR6PB5fLddrLHNhmIE/87InTmueGG24gMjKS7777jhEjRnDttddy5513UlxcTFRUFK+88go9e/Zk8eLFPPbYY3z00UfMmDGD3bt3s2PHDnbv3s1tt93Gb37zGwBiYmLIz89n8eLFzJgxg+TkZNavX09aWhqzZ89GRJg/fz5333030dHRjBgxgh07dvDRRx+dkG3x4sX07duXa665hjfeeKOi8GdmZnLbbbexY8cOAJ555hmGDx/Oa6+9xmOPPYaI0L9/f2bNmnXa27A+grvwe6ypx5hgtGfPHr788ktcLhdHjx5l2bJlhIaG8vnnn/P73/+ed95554R5Nm/eTHp6Onl5efTo0YPp06efcN77d999x4YNG2jXrh0jRoxg+fLlDBkyhFtvvZWlS5fSuXNnJk+eXGuuN954g8mTJzNx4kR+//vfU1paSlhYGHfccQejRo3ivffew+PxkJ+fz4YNG3jooYf48ssvSU5OJjs7u8G3U218XvhFxAWsBPaq6gQR6QzMAZKAVcAvVPXkjXX1VNEfv+3xG3PGTrZn3tjnxV911VUV3zByc3OZMmUKW7duRUQoLS2tcZ5LLrmEiIgIIiIiaNWqFZmZmXTo0OG4aYYOHVoxbODAgWRkZBATE0OXLl0qzpGfPHkyzz///AnLLykpYf78+Tz++OPExsYybNgwPvnkEyZMmMCiRYt47bXXAHC5XMTFxfHaa69x1VVXkZycDEBiYmLDbJw6aIyDu3cCVX929r/A31W1G3AEuMlXK7aDu8YEp+jo6IrH999/P2PGjGH9+vV8+OGHtZ7PHhERUfHY5XLhdrvrNU1tPvnkE3JycujXrx+pqal88cUXvPHGG3WevzH5tPCLSAfgEuBF73MBxgJveyeZCVzuq/Xb6ZzGBL/c3Fzat28PwKuvvtrgy+/Zsyc7duwgIyMDgLlz59Y43RtvvMGLL75IRkYGGRkZ7Ny5k88++4zCwkIuvPBCnnnmGcA5HpKbm8vYsWN56623yMrKAgiqpp4ngN8A5d8Bk4AcVS3/N7oHaF/TjCIyFZgKkJKSwuLFi0975Rv2bgDg26+/ZVv4ttOe3x/KDzIFgkDKCoGVt6lkjYuLIy8v75TTeTyeOk13Jo4dO0ZYWBilpaUUFRVVrO/222/ntttu48EHH2TcuHGoKnl5eRQWFuJ2u8nLy6uYt3weVSU/P7/iefXpwWm6KS4uxu1287e//Y1x48YRHR3N4MGDKS0tPe71FhYW8vHHH/Poo48eN/zcc8/lzTff5OGHH+aOO+7ghRdewOVy8fjjjzNs2DDuvvtuRo4cicvlon///jz77LMnvO66btvi4uK6v2dU1Sc3YALwtPfxaOAjIBnYVmWajsD6Uy0rLS1N6+OJr55QZqBZhVn1mt8f0tPT/R2hzgIpq2pg5W0qWTdu3Fin6Y4ePerjJA3rdPPm5eWpqmpZWZlOmzZNH3/8cV/EqlFds9b0twJWag011ZdNPSOAy0QkA+dg7ljgSSBeRMq/aXQA9voqgLXxG2MawgsvvMDAgQPp27cvubm53Hrrrf6OdEZ81tSjqr8DfgcgIqOBe1T1ehF5C5iE889gCvC+rzJYG78xpiFMnz6d6dOn+ztGg/FHlw2/Be4WkW04bf4v+WpFtsdvjDEnapQfcKnqYmCx9/EOYGhjrLfUU4oguEJO/xeFxhgTrIK+k7ZQCeofJxtjzGkL7sLvKcUltrdvjDFVBXfhLyu1njmNCWBjxozhk08+OW7YE088wbRp02qdZ/To0axcuRKAiy++mJycnBOm+ctf/sJjjz120nXPmzePjRs3Vjz/4x//yOeff3468U/Kn903B3fh91hTjzGBbPLkycyZM+e4YXPmzDlpR2lVzZ8/n/j4+Hqtu3rhf/DBB/nJT35Sr2VVV7375sYW1FXR2viNaTh33QVrau6VGY8ninr0yszAgfDESXplnjRpEvfddx8lJSWEh4eTkZHBvn37GDlyJNOmTWPFihUUFRUxadIk/vSnP50wf2pqKitXriQ5OZmHH36YmTNn0rp1a9q0aUNSUhLgnKP//PPPU1JSQrdu3Zg1axZr1qzhgw8+YMmSJTz00EO88847/PnPf2bChAlMmjSJhQsXcs899+B2uznnnHN45plniIiIIDU1lSlTpvDhhx9SWlrKW2+9Ra9evU7IdTrdN/fr16/Bu28O7j3+MmvjNyaQJSYmMnToUD7++GPA2du/+uqrEREefvhhVq5cybp161iyZAnr1q2rdTmrVq1izpw5rFmzhvnz57N69eqKcVdeeSUrVqxg7dq19O7dm5deeonhw4dz2WWX8eijj7JmzRq6du1aMX1xcTE33HADc+fO5fvvv8ftdlf0wwOQnJzM6tWrmTZtWq3NSeXdN19xxRX8+9//ruhRtLz75rVr17J69Wr69u3Lpk2beOihh1i0aBFr167lySefPKNtCkG+x+8uc1vhN6aBnGzPPC+vyGfdMpc390ycOJE5c+bw0kvOT3/efPNNnn/+edxuN/v372fjxo3079+/xmUsW7aMK664ghYtWgBO23+59evXc99995GTk0N+fj4XXXTRSfNs2bKFzp0706NHDwCmTJnCU089xV133QU4/0gA0tLSePfdd0+Y/3S7b16yZEmDd98c1IW/1GMHd40JdBMnTmT69OmsXr2awsJC0tLS2LlzJ4899hgrVqwgISGBG264odbumE/lhhtuYN68eQwYMIBXX331jDvHK+/aubZunat23wxOB29RUVFMmDDhjNZ7OoK+qcfa+I0JbDExMYwZM4Zf/epXFQd1jx49SnR0NHFxcWRmZlY0BdXmggsuYN68eRW9eladPi8vj7Zt21JaWsrrr79eMTw2NrbGXjF79uxJRkYG27Y5Pf7OmjWLUaNG1fn1nG73zaNGjWrw7puDu/DbefzGBIXJkyezdu3aisI/YMAA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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAY4AAAEWCAYAAABxMXBSAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3dd3wUdf748dc7HUJACEUpCgiIIFKCgGABK9gQha94cp7tVE70xPMU7zz1VH7qWU45RU8PGxZsh4cKijRRsAAKStXQJKH3BEh///74zGY3YVM2ZLNZeD8fj31Mn3nPZDPv/Xxm5jOiqhhjjDGVFRPpAIwxxkQXSxzGGGNCYonDGGNMSCxxGGOMCYklDmOMMSGxxGGMMSYkljiMMcaExBKHMdVIRNaJyDmRjsOYcLLEYYwxJiSWOIwJMxFJFJGnRWSj93laRBK9aY1F5GMR2S0iO0XkSxGJ8abdLSKZIpIlIqtE5OzI7okxTlykAzDmCPBXoA/QDVDgf8C9wN+APwEZQBNv3j6AisgJwCjgFFXdKCKtgdiaDduY4KzEYUz4XQU8qKpbVXUb8Hfgt960fOAY4DhVzVfVL9U1IFcIJAKdRCReVdep6uqIRG9MKZY4jAm/5sD6gOH13jiAx4F0YLqIrBGRMQCqmg7cDjwAbBWRSSLSHGNqAUscxoTfRuC4gOFjvXGoapaq/klV2wKXAHf4rmWo6luqepq3rAKP1WzYxgRnicOY6hcvIkm+D/A2cK+INBGRxsB9wBsAInKRiLQTEQH24KqoikTkBBE5y7uIngMcAIoiszvGlGSJw5jqNxV3ovd9koCFwI/AT8D3wMPevO2BGUA28DUwXlVn465vPApsBzYDTYF7am4XjCmb2IucjDHGhMJKHMYYY0JiicMYY0xILHEYY4wJiSUOY4wxITkimhxp3Lixtm7dukrL7tu3j+Tk5OoNKIyiKd5oihWiK95oihUs3nA6lFgXLVq0XVWbHDRBVQ/7T1pamlbV7Nmzq7xsJERTvNEUq2p0xRtNsapavOF0KLECCzXIOdWqqowxxoTEEocxxpiQWOIwxhgTEkscxhhjQmKJwxhjTEgscRhjjAmJJQ5jjDEhscRhTA1avBi+/jrSURhzaI6IJ8eNqS3+8hfYsgUWLYp0JMZUnZU4jKlBu3bB7t2RjsKYQ2OJw5gKFBVBq1bw6adHH/K69u51H2OimSUOYyqwdy9kZMBjj3WslnVlZVVDUMZEkCUOYyqwZ0/1rWvvXsjNhby86lunMTXNEocxFaiuqqWiIn9pw0odkZGeDmvXRjqK6GeJw5gKVFeJY98+UHX9oSSj11+HP/6xemKoLrt2QYMG8PnnkYvh3/+GTz8NbZlrr4Wbbw5PPEcSSxwmqjz7LNxxR81uMzBx7N9fPesJpcQxeTK88UbVtxsO69e75LdkSWS2r+oSwKBBoS2XkeFiN4fGEoeJKh99BB984PqzsuDCC8Nf9RBYOtiw4eDpRUXwyisVl0wC1xNKiWPTJvcLf9680Pb1kUfg+uvLn+fll+Gnn8qfZ9kyf0nJZ8cO1922rfLxVCff9qH84z5tGuTk+Ie3bXPHsyJLlhy8z8bPEoeJCjt3uu62bf7+n36CqVPhiy/Cu+3AE9Ovvx48/euv4brr4Jxzyl9PVRPH5s3uJHbaadC2beWXmzatZFVOQYE7Xr4TYkEB3HgjjB9f9jq+/x5OOgm+/LLkeN+Je+vWysfjW65r14qTVVm2boUPP4RVq/zjSsfms3gxXHABjB7thvfvd9WFe/f6S44rVsDIkZCf71/uxx+hWzd4992S6/vrX2HWrKrFfbixxGFqve++gyZN4OefXeLIznZ3JW3f7qZv2RLe7QcmDt8JLy/Pf/JZuNDfLe+EGJgsKltVpVq5X8jBbNjgTrS+RHHHHa6E9s03bnjTJigsdImpLL4T9MqVJccHJvJQLFrkTsxffVVy/OTJzVmwwD/8+utwyy0HL//kkzBkCMyf7x/30UcwbNjBx2nXLtf1rTcwVt8+jx4NL7wAc+b4p/mOz7RprqvqEssjj9S+KsNIscRhar2ff3bVQb/84v/n37Wraolj2bKKf+2vWOHvX74cvv0WYmOhZcv9zJ7txp93HiQnu35f4gBYs6bs9ValxLF798G37hYUHDxf6WqVoiLIzHTz7t7tjte//uWmZWa6rq/arbzEkZFRcl7fdsqqqsrPhxNOcNeigklPL7lecKWAceM6cOqpbnjxYvjd71xJKDu75PK+k/qHH0J8PLRpAy++CO+/D3/6U8l5fbHt23dwrL4kU7eu6z75pEtA4EpZADNmuP0dOBC6dHH9wUqcRyJLHKbW8yWIdevcMxDgTmS+f/7KVpcUFkKfPu6XY1m++AI6dXLXE8DdhTN5sruDqFu33cyd607GvuqxnTtd4ujZ0w1v3OhfV+BJ9r77Sp64fCWO7GyX+P773+DxBDupr1njkujNN8OBA26/und3VWW+JLprV0Jx9cu330LLlv7lf/3VlZaWLi17Gz6+hOHrnnUWXHLJwVVV//sfPPYY/PCDS/S33upiK231atfNyHBJeeJElyjA7QeU/FXvixHccfcl6fnzoV07OP54//TAEgv4j0V2tkucgcd/zBh3DH2lks8+c/v1wQcucYi4BDtrFkyf7i95WeJwrJFDU+v5EkdgSeCUU/z9lS1xbNrkTiLBqpNU4Q9/cCcTcCePvn1dCQVc4ujefRcff9y8+FcvQIsW7uLrww+7k2ZmpvuFP3Ag9OrlqtjWr4cJE9xJ12fvXjd/jx4uUS1f7k7CTZocHHNpK1a4RPP6627Zdu38dzedf76r89+2LbF4/htucPv3wQdw1VUuCfTr5z9hb97stn/iie6EGSiwxLFmjb9K56qrXNd3Mh4/3lU/xcf7l33nHbjmmpLr85U4Vqxw1Wbr1sHQoW5cnHc2WrAAmjVzf9cff3RJ8YYb4LjjSt7VdtppJUta6enu+Ldo4YZ934uMDGjUCP7xD/+8X30FV1/tL33Vr++2+fjjbpvnn++uD40aVTL+DRvsojlYicNEAV/iWL48+PTKJg7fbZil6+t963jhBZg50z9PZqa/miMvD/r02Um9eu7k4pOT46pI7rwTjj7aLfOnP7lf+f/6lytpTJjg5vVdWE1KciUO369n3375khT4T5DBSgPLl/t/+Y4bBy+9BE2bupLRkiXuhL11qz9xZGa6E+9ll7mqnV9/9ScN3z507uyWX7bMnTB9d675Shq//uruwPLxXZDet88lkSVLXMwTJ8Kxx7oSzpQpB8fuSxwLFrikkZrqqpnAVa/l5LjrIEOHQkqKW+/8+a4UMnasG+czZAi0bl1y/d9+6+8v/b3wVTP6fPON27+//c2VoM46yy2fmwtXXgl16hz8XcnJ8X8fj2RW4jC1XrASR6BQE8fate7kUFDgfkV36VLypA3uF+lzz/mHN22CunULGTHCJZhAjz3mroE0b+6qqlascMO+qpdAycnu1+3evQfH/cYbrs49IcGVdh54wK0nUGqqO+l+952bb/Vqt1/XXeeqWurXd/X1K1eeVGK5vn1dt1WrknckBbr2Wle95Kvimj7dn9wyMlxC8e1jYJXNW2/5+xcvht/8xsUxcaI7zomJcNNNrtQWeA3oxBNdSWXAADdcVORO1uBKa4sXu/1s1MiNmzwZeveGiy92yeWss/xVTUOGuGsU333nEsSqVQf/TefNcyWio45yVZa+axpt2rjSTufO/nl79XJ3Vn39tbsza+pU/zSrrgJUNWwfYCCwCkgHxgSZngi8403/FmjtjT8XWAT85HXPClhmjrfOxd6naUVxpKWlaVXNnj27ystGQjTFW9lYzzxT1VUQBP/ExKgWFJRcZscO1aIi//CYMSWXWbpU9c47Xf+IEarnnVf+NsDFu3ixf/jTT1W3bPFv49JLVY86yk178EHVuDjVAQNUr75a9ZZb3Pjf/171xBNVu3VTHTIk+HZ8+xsXp9qvn2rjxqqpqapJSaqXX+6f729/8/dPnOhiOOMM/7jERH//8uVu+g03VLyfpT916pTcZpMm5c//wQeqH3/s+q+91sUeOL1nT9f97W/9f6uHHvqxxDzr16s+8YR/P3r39h/nbdtUV6xw/fPmuXn++lfVHj3cMQqM+fTTVceO9a+3eXP3XSksVB01yo2bPt2ta+ZMN5yc7Obx/c3++9+S8f/3v4fn/1kwwEINdm4PNrI6PkAssBpoCyQAS4BOpeb5A/CC1z8ceMfr7w409/pPAjIDlpkD9AwlFksctceyZaoXX6y6b1/lY+3cueKT28yZqmvWuPnXrnUnkKefVs3LU/3xR/8JxfeZNEn1lFNKjktMVP3iC9Vbby07caiqnnqqG87OLhmn70QDqt9+6xLL2rVuWk6O6qJFLpm99ZZqbKx/3sB+3+eOO/z9l16q2qGDauvWqv/v//nHb93qkgr4t+M7GZ5++lbduNE/ry+x/v3vJU+A06ZVfGzvu8/fP2OG6ujRrr9bN9W+fQ+ePydHdf/+kgnH9zn2WNXHH3f948f7j93bb3+t4P5OvoS/c6d/uUceCf7d2LHDnej/9z/Vm25y8954oz/mQYPcfF26uOFLLvEvm5ur+u67Lomoqm7e7Obp188Nz57tEv+BAy75dezopj/zTO3/PwsUbYnjVOCzgOF7gHtKzfMZcKrXHwdsB6TUPALsBBLVEkeFanu8Dz/svnXz5/tjfeIJl1BUVZ98UrV7d9UXXnC/2vPyVJs1K3lyL+sEV7++++f3nUBAtU+fg+dr0UK1XTtVEdXLLnPb8U1TdSfh229Xfe891XHjVJ96yp0wffHOm6d6//0H75vvpJ6Q4E5K5bnySjfviBEu5t/8pmSMa9e6X9ngjk+/fi5hTZ3qxjVt6tYzbJhLKL6T7UMPuekjR/6iqiX3S1X1p5/84/LyVPfscf1du/qPIaj26uV+xefnu+VGjHDHa98+1V9/dfOMGuWmXXKJG/7Pf/wlH1XViy5y46+4wsX9xz+6E/WBA+7v61u3quqsWbP1nnv8JQmfjz92JRjfyT2Y/fvd/i9Z4v4u+fkuSYPqySe7eZo21eIfDGUpKlI9/ni336X9/vfuuzt9uuqmTbX//yxQOBKHuGnVT0SGAgNV9QZv+LdAb1UdFTDPUm+eDG94tTfP9lLruVlVz/GG5wCpQCHwAfCwBtkJEbkRuBGgWbNmaZMmTarSfmRnZ1OvXr0qLRsJtT3eBx/sxOzZTbnnnhX07bsaOIqLLz6NIUMyuOmmNQwceEaJ+S+6aCNTpx5DUZG73SctbSeLFjUqnt64cS7XXruW/PwYnn66Q/H4447bx/r1yYgoZ5zhbv354oumNG6cy5//vJK77+4KwN/+towBA7Zx663d6dNnByNGlF2BXdGxzcysw3vvteS887bQqVP5D2rMm5fKvfd24eyzt3DvvSvIzxeys+O44opTadlyPy+/vJA33jiWCRPaMn78ouL9b9NmH2PGdGHkyNWceGIWe/bEs39/LMcck+PFGMvbbx/LkCHLaNy4Ll99lUqdOkWkpe0q3vbq1cn8+mtdBgxwxyUnJ4aEhCLWrk1mypTmfPllEz74YH6JO6xUYd++OOrVKyje19TUXJKSisjLi2HHjoTiGHw+/7wZTz7ZgYkTv6NJk9xyj0d1f29VYfz44xkwYCudOmXx0ktteOut45g2bS5JSUVlLnfgQCzx8UXExZV/Xqzt/2eBDiXWAQMGLFLVngdNCJZNquMDDAX+EzD8W+DZUvMsBVoGDK8GGgcMd/bGHR8wroXXTQGmA1dXFIuVOGqHX35x9fvgfhnOnj1bf/jBDZ91lurLL5ddmvB9nnpK9ZhjVDt1ciWRDz7wr3/wYFf//tZbrrrkm29Ud+/2T1+xQjUz0/WPH++qHrZurXz81XlsCwrcMfBVMfn84x/+fdqzR3XChJLXaiqrqrHu2XNwTFVVVOTWVxnh/t4WFh5ctXgoavP/WWnhKHGE866qTKBVwHBLb1yweTJEJA5oAOwAEJGWwGQvMaz2LaCqmV43S0TeAnoBr4drJ0z12LwZ2rf3D6enQ//+/kb7li6FTz6BevX8TwtPmOBvpK9LF/f8xYUX+psYjyl1M/k777jnEBIS3HDv3iWndwx4gd/Ike4TKbGx7q6p0v78Z39//frubqmaVL+++1QHkepb16GKifE/6W8OXTif41gAtBeRNiKSgLv4XfrO7inA77z+ocAsVVUROQr4BHcn1jzfzCISJyKNvf544CJcqcXUcr7790sPr1vnulu3umcHhg/3P+V8/vnu1kffw2Xr10OHDu4kUDppgLvt05c0jDHhE7YSh6oWiMgo3AXwWOBlVV0mIg/iij9TgAnARBFJx10AH+4tPgpoB9wnIvd5484D9gGfeUkjFpgBvBSufTDVx/cg2dlnu2cRZsxw9+37EofPwIHumYH9+90zAyL+kkFt+fVqzJEurA8AqupUYGqpcfcF9OcAw4Is9zDwcBmrTavOGE343XILfPyx65882T149e67MGzYqezc6ZqIiItzbS0NHuweUtu48eDmL4wxtYM9OW7CqrDQNVWRk+Oe2E1Jcc05LF4Mjz/umsUoXfLo1SsysRpjKscShwmrNWv8b2Br1sx1RVyDc4MGzeHDD/vTr1/k4jPGhM4ShwmrwPaCdu0qOU0EnnmmZuMxxhw6ax3XHLL773ctwhYVuYbtAt8HHZg4KnontzEmOliJw1TJ3LnufQgbNsCDD7pxycnw0EPu+YT773etuD7wgGv6+swzXaupxpjoZ4nDlCszE957zz1057vLafZs16T1o4+WLEU89JDrbt7s3jdx+eXuFtqRI+Guu2o+dmNMeFhVlSnXyy/D6NEl30Hge13o118Hf7nSxInuxUIbNriX+VjSMObwYonDlMv30h/fA3zgbxJk7153G+3Agf5pV1zh3gqXk+OaELE7pow5/FhVlSmXL3EEljh8b67bs8cljtNPhzFj/A/ugXtP9AUX1GioxpgaYonDlEk1eInDlzh+/NG9frV1a3dXFcCLL7qur70pY8zhx6qqTJl8F7kheImjwL2agdat/dN8CePMM8MenjEmQqzEYQ5y4olw8cUwaJB/XLASh09g4hg0CD7/3N11ZYw5PFniMCUUFcHKle5zzDFuXM+eB5c4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FnqfJ3GlDxNE74Dn4++5x3V9L9byJY6OHf1tXXXtCp9+Cq8f9BijMSYUAwYM4LPAX2fA008/zciRI8tcpn///iz0HsK64IILgrb59MADD/DEE0+Uu+0PP/yQ5QH10vfddx8zZswIJfygamPz65WtqnoZyAL+z/vsBV4JV1DRzlfddMEFcNttMH+++wCsWgUnn+we8Dv/fOjRwyWOY45xpRNjTNVdeeWVTJo0qcS4SZMmVbq9qKlTp1b5IbrSiePBBx/knHPOqdK6arvKJo7jVfV+dQ0WrlHVv+MeAjRBJCe7O6n++1/Xsu2pp0LTgMbfu3RxJZBPP3UXx+vWjVysxhxOhg4dyieffFL80qZ169axceNGTj/9dEaOHEnPnj3p3Lkz999/f9DlW7duzXavbnns2LF06NCB0047rbjpdXDPaJx55pl07dqVyy+/nP379zN//nymTJnCn//8Z7p168bq1au55ppreP/99wH3hHj37t3p0qUL1113Hbm5ucXbu//+++nRowddunRhZXkv4yklks2vV/auqgMicpq6FmsRkX7AgUPe+mHs+ONLDscEpOjf/KZmYzEmEm6/3b3wrDIKC+tQmTYOu3WDp8tpVb1Ro0b06tWLadOmMXjwYCZNmsT//d//ISKMHTuWRo0aUVhYyNlnn82PP/7IySefHHQ9ixYtYtKkSSxevJiCggJ69OhBWpp7hOyyyy5j+PDhpKSkcO+99zJhwgRuvfVWLrnkEi666CKGDh1aYl05OTlcc801zJw5kw4dOnD11Vfz/PPPc/vttwPQuHFjvv/+e8aPH88TTzzBf/7znwqPQ6SbX69sieNm4DkRWec90f0scHg9ClkDmrgGbxk0KLJxGHM4C6yuCqymevfdd+nRowfdu3dn2bJlJaqVSvvyyy8ZMmQIdevWpX79+lxyySXF05YuXcr5559Ply5dePPNN8tslt1n1apVtGnThg4dOgDwu9/9jrlz5xZPv+yyywBIS0tj3bp1ldrHSDe/Xtm7qpYAXUWkvje8V0RuB3485AiOIEuXupKHvYzJHAnKKxmUlpV1oNpaxx08eDCjR4/m+++/Z//+/aSlpbF27VqeeOIJFixYQMOGDbnmmmvIyana636uueYa3nzzTfr27curr756yM3XJyYmAq7F3UNtdLFhw4YsWbKEzz77jBdeeIF3332XZ555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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PidM1sHrnZ16"
      },
      "source": [
        "#Evalutae model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4pI0kXNmzO8o"
      },
      "source": [
        "def correct_count(output, target, topk=(1,)):\n",
        "    \"\"\"Computes the top k corrrect count for the specified values of k\"\"\"\n",
        "    maxk = max(topk)\n",
        "\n",
        "    _, pred = output.topk(maxk, 1, True, True)\n",
        "    pred = pred.t()\n",
        "    correct = pred.eq(target.view(1, -1).expand_as(pred))\n",
        "\n",
        "    res = []\n",
        "    for k in topk:\n",
        "        correct_k = correct[:k].contiguous().view(-1).float().sum(0, keepdim=True)\n",
        "        res.append(correct_k)\n",
        "    return res\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9ci39QLszRDv"
      },
      "source": [
        "def evaluate(net, dataloader, criterion):\n",
        "    net = net.eval()\n",
        "    loss_tr, n_samples = 0.0, 0.0\n",
        "\n",
        "    y_pred = []\n",
        "    y_gt = []\n",
        "\n",
        "    correct_count1 = 0\n",
        "    correct_count2 = 0\n",
        "\n",
        "    for data in dataloader:\n",
        "        inputs, labels = data\n",
        "        inputs, labels = inputs.to(device), labels.to(device)\n",
        "\n",
        "        # fuse crops and batchsize\n",
        "        bs, ncrops, c, h, w = inputs.shape\n",
        "        inputs = inputs.view(-1, c, h, w)\n",
        "\n",
        "        # forward\n",
        "        outputs = net(inputs)\n",
        "\n",
        "        # combine results across the crops\n",
        "        outputs = outputs.view(bs, ncrops, -1)\n",
        "        outputs = torch.sum(outputs, dim=1) / ncrops\n",
        "\n",
        "        loss = criterion(outputs, labels)\n",
        "\n",
        "        # calculate performance metrics\n",
        "        loss_tr += loss.item()\n",
        "\n",
        "        # accuracy\n",
        "        counts = correct_count(outputs, labels, topk=(1, 2))\n",
        "        correct_count1 += counts[0].item()\n",
        "        correct_count2 += counts[1].item()\n",
        "\n",
        "        _, preds = torch.max(outputs.data, 1)\n",
        "        preds = preds.to(\"cpu\")\n",
        "        labels = labels.to(\"cpu\")\n",
        "        n_samples += labels.size(0)\n",
        "\n",
        "        y_pred.extend(pred.item() for pred in preds)\n",
        "        y_gt.extend(y.item() for y in labels)\n",
        "\n",
        "    acc1 = 100 * correct_count1 / n_samples\n",
        "    acc2 = 100 * correct_count2 / n_samples\n",
        "    loss = loss_tr / n_samples\n",
        "    print(\"--------------------------------------------------------\")\n",
        "    print(\"Top 1 Accuracy: %2.6f %%\" % acc1)\n",
        "    print(\"Top 2 Accuracy: %2.6f %%\" % acc2)\n",
        "    print(\"Loss: %2.6f\" % loss)\n",
        "    print(\"Precision: %2.6f\" % precision_score(y_gt, y_pred, average='micro'))\n",
        "    print(\"Recall: %2.6f\" % recall_score(y_gt, y_pred, average='micro'))\n",
        "    print(\"F1 Score: %2.6f\" % f1_score(y_gt, y_pred, average='micro'))\n",
        "    print(\"Confusion Matrix:\\n\", confusion_matrix(y_gt, y_pred), '\\n')\n",
        "\n",
        "\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gognlcW3t-R1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "5a8108e6-137e-4622-cbe7-4240b08f067e"
      },
      "source": [
        "criterion = nn.CrossEntropyLoss()\n",
        "# Get data with no augmentation\n",
        "trainloader, valloader, testloader = get_dataloaders(augment=False)\n",
        "print(\"Test\")\n",
        "evaluate(net, testloader, criterion)\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Test\n",
            "--------------------------------------------------------\n",
            "Top 1 Accuracy: 73.279465 %\n",
            "Top 2 Accuracy: 86.458624 %\n",
            "Loss: 0.019549\n",
            "Precision: 0.732795\n",
            "Recall: 0.732795\n",
            "F1 Score: 0.732795\n",
            "Confusion Matrix:\n",
            " [[308   3  34  20  49   9  44]\n",
            " [ 13  36   2   1   3   1   0]\n",
            " [ 38   0 284  11  84  32  47]\n",
            " [ 11   0  10 797  12  15  50]\n",
            " [ 56   0  54  19 425   8  91]\n",
            " [  7   0  26  16   7 351   8]\n",
            " [ 31   0  21  39  78   9 429]] \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "YNYhCmP3xpDc"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}